
using Progress.Lang.*.
using OpenEdge.WebSpeed.*.

routine-level on error undo, throw.

class OpenEdge.WebSpeed.WebUtil: 

    /* Unsafe characters that must be encoded in URL's.  See RFC 1738 Sect 2.2. */
    define public static property URLUnsafe as character no-undo initial " <>~"#%~{}|~\^~~[]`":U
        get.
        private set.

    /* Reserved characters that normally are not encoded in URL's */
    define public static property URLReserved as character no-undo 
        initial "~;/?:@=&":U
        get.
        private set.
    


    /**
        Description: Encodes unsafe characters in a URL as per RFC 1738 section 2.2.
          <URL:http://ds.internic.net/rfc/rfc1738.txt>, 2.2
        Input Parameters: Character string to encode, Encoding option where "query",
          "cookie", "default" or any specified string of characters are valid.
          In addition, all characters specified in the global variable url_unsafe
          plus ASCII values 0 <= x <= 31 and 127 <= x <= 255 are considered unsafe.
        Returns: Encoded string  (unkown value is returned as blank)
        Global Variables: url_unsafe, url_reserved
    
    */
    method public static character url-encode
        (input p_value as character,
        input p_enctype as character) :
        define variable hx          as character no-undo initial "0123456789ABCDEF":U.
        define variable encode-list as character no-undo.
        define variable i           as integer   no-undo.
        define variable c           as integer   no-undo.
 
        /* Don't bother with blank or unknown  */
        if length(p_value) = 0 or p_value = ? then 
            return "".
   
        /* What kind of encoding should be used? */
        case p_enctype:
            when "query":U then              /* QUERY_STRING name=value parts */
                encode-list = URLUnsafe + URLReserved + "+":U.
            when "cookie":U then             /* Persistent Cookies */
                encode-list = URLUnsafe + " ,~;":U.
            when "default":U or 
            when "" then /* Standard URL encoding */
                encode-list = URLUnsafe.
            otherwise
            encode-list = URLUnsafe + p_enctype.   /* user specified ... */
        end case.

        /* Loop through entire input string */
        assign 
            i = 0.
        do while true:
            assign
                i = i + 1
                /* ASCII value of character using single byte codepage */
                c = asc(substring(p_value, i, 1, "RAW":U), "1252":U, "1252":U).
            if c <= 31 or c >= 127 or index(encode-list, chr(c)) > 0 then 
            do:
                /* Replace character with %hh hexidecimal triplet */
                substring(p_value, i, 1, "RAW":U) =
                    "%":U +
                    SUBSTRING(hx, integer(truncate(c / 16, 0)) + 1, 1, "RAW":U) + /* high */
                    SUBSTRING(hx, c modulo 16 + 1, 1, "RAW":U).             /* low digit */
                assign 
                    i = i + 2.   /* skip over hex triplet just inserted */
            end.
            if i = LENGTH(p_value,"RAW":U) then leave.
        end.

        return p_value.
    end.

    /**
    Description: Decodes URL form input from either POST or GET methods or
      encoded Cookie values.  CR/LF pairs are replaced with LF.
    Input: String to decode
    Returns: decoded string
    
    */    
    method public character url-decode
        (input p_in as character) :
        define variable out as character no-undo.
  
        /* Copy and replace from p_in to out.  Note that p_in will have
           End-of-Line replaced with a CF/LF.  We need to replace this with the
           4GL-standard LF so when an HTML <TEXTAREA> is saved in a database, it
           won't contain extra characters. */
        out = replace(p_in, "%0D%0A":U, "~n":U).

        define variable webContext as WebContext no-undo.
        webContext = new WebContext().

        return webContext:url-decode(out).
    end .     
    
end class.